package future;

import org.junit.Test;

import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * CompletableFuture测试
 *
 * @author codefish
 * @version 1.0
 * @date 2022/07/24 下午 01:31
 */
public class CompletableFutureTest {

    /**
     * 无返回值，不指定线程池，则默认使用ForkJoinPool
     */
    @Test
    public void noReturn() throws InterruptedException, ExecutionException {
        CompletableFuture<Void> result = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "[hello]");
            try {
                TimeUnit.MILLISECONDS.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        System.out.println(Thread.currentThread().getName() + "[" + result.get() + "]");
    }

    /**
     * 无返回值，自定义线程池
     */
    @Test
    public void noReturnWithThreadPool() throws InterruptedException, ExecutionException {
        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        CompletableFuture<Void> result = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "[hello]");
            try {
                TimeUnit.MILLISECONDS.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, threadPool);
        System.out.println(Thread.currentThread().getName() + "[" + result.get() + "]");
        threadPool.shutdown();
    }

    /**
     * 有返回值
     */
    @Test
    public void withReturn() throws InterruptedException, ExecutionException {
        CompletableFuture<String> result = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "[hello]");
            try {
                TimeUnit.MILLISECONDS.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello world";
        });
        System.out.println(Thread.currentThread().getName() + "[" + result.get() + "]");
    }

    /**
     * CompleteFuture实现了Future接口，可以完成所有Future能做到的事情
     */
    @Test
    public void workLikeFuture() throws InterruptedException, ExecutionException {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "进入----");
            int res = ThreadLocalRandom.current().nextInt(500);
            try {
                TimeUnit.MILLISECONDS.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return res;
        });
        System.out.println(Thread.currentThread().getName() + "继续做其它事情----");
        System.out.println(Thread.currentThread().getName() + "获得异步结果：" + completableFuture.get());
    }

    /**
     * 注册监听者，当异步任务完成或异常时调用相应方法
     */
    @Test
    public void callbackWhenCompleted() {
        CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "进入----");
            int res = ThreadLocalRandom.current().nextInt(500);
            try {
                TimeUnit.MILLISECONDS.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (res > 250) {
                throw new RuntimeException("运行结果异常：" + res + "大于250");
            }
            return res;
        }).whenComplete((v, e) -> {
            if (e == null) {
                System.out.println(Thread.currentThread().getName() + "异步任务执行完成后回调，处理结果：" + v);
            }
        }).exceptionally((e) -> {
            e.printStackTrace();
            System.out.println(Thread.currentThread().getName() + "异步任务出现异常时回调，异常信息：" + e.getMessage());
            //出现异常时返回的默认值
            return -1;
        });
        System.out.println(Thread.currentThread().getName() + "继续做其它事情----");
        //等待异步任务执行完成
        try {
            TimeUnit.MILLISECONDS.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * get()和join()区别
     */
    @Test
    public void getOrJoin() {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            return "hello";
        });
        //需要处理异常
        try {
            System.out.println(completableFuture.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        //不需要处理异常
        System.out.println(completableFuture.join());
    }

    /**
     * 测试Runnable接口的使用
     */
    @Test
    public void testRun() {
        Runnable runnable = () -> System.out.println(5);
        runnable.run();
    }

    /**
     * 测试Function接口的使用
     */
    @Test
    public void testFunction() {
        Function<String, Integer> func = (str) -> Integer.parseInt(str);
        Integer res = func.apply("123");
        System.out.println(res);
    }

    /**
     * 测试Consumer接口的使用
     */
    @Test
    public void testConsumer() {
        Consumer<Integer> consumer = (item) -> {
            item = item * 2;
            System.out.println(item);
        };
        consumer.accept(5);
    }

    /**
     * 测试BiConsumer接口的使用
     */
    @Test
    public void testBiConsumer() {
        BiConsumer<Integer, Integer> consumer = (arg1, arg2) -> {
            System.out.println(arg1 * arg2);
        };
        consumer.accept(5, 7);
    }

    /**
     * 测试Supplier接口的使用
     */
    @Test
    public void testSupplier() {
        Supplier<Integer> supplier = () -> {
            return ThreadLocalRandom.current().nextInt(300);
        };
        System.out.println(supplier.get());
    }



}


